#!/usr/bin/env bash

# TODO 1、赋值变量【注意：等号两边不能有空格】
app_name='docker-jenkins-springboot'
# 获取指定名称的容器ID【-a表示获取所有容器，-q表示只获取容器Id，"name=^/${app_name}$"表示指定容器名称为${app_name}】
container_id=$(docker ps -a -q -f "name=^/${app_name}$")
# 获取脚本所在目录
project_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

# 打印容器的日志信息方式：1、使用 echo 命令【默认自动换行】   2、使用 printf 格式化输出【换行需要显式添加\n】
echo "🚀 开始快速构建部署..."
echo "📦 项目名称: $project_dir"
echo "🐳 镜像名称: $app_name"
echo "⚙️ 容器名称: $app_name"

# TODO 2、停止并删除已存在的同名容器
# -n表示判断变量是否为非空，表示"not null"。该示例中表示判断 ${container_id} 是否为非空，不为空则进入 then 分支
echo "⏳ 检查并停止已存在的同名容器..."
if [ -n "${container_id}" ]; then
  printf "🛑 停止容器 " && docker stop "${app_name}"
  printf "🧹 删除容器 " && docker rm "${app_name}"
else
  printf '⚠️ 容器 %s 不存在，跳过 stop/rm ====\n' "${app_name}"
fi

# TODO 3、清理悬空镜像【即：在进行重新镜像构建时，由于没有改变镜像Tag，会导致旧镜像变成悬空镜像（dangling image），需要及时清理】
#         示例：第一次构建：docker build -t myapp:v1 .
#              第二次构建：docker build -t myapp:v1 .
#              新镜像: myapp:v1 (IMAGE ID: def456)
#              旧镜像: <none> <none> (IMAGE ID: # abc123) ←- 变成悬空镜像
dangling_images=$(docker images -f "dangling=true" -q) # 获取所有悬空镜像的ID
if [ -n "${dangling_images}" ]; then
  printf '🧹 删除悬空镜像 ' && docker rmi ${dangling_images} || true
else
  printf "⚠️ 没有悬空镜像需要删除\n"
fi

# TODO 4、使用本地系统的 Maven 构建项目
echo "🔨 构建 Maven 项目..."
mvn clean package -DskipTests # 执行 Maven 构建，先清理再打包，并且跳过单元测试。
# $?表示上一条命令的退出状态码（0=成功；非0=失败），-ne：表示数值比较运算符，表示 "not equal"（不等于）
if [ $? -ne 0 ]; then  # 判断上一条命令的退出码是否不等于 0（即是否失败）
  printf "❌ Maven 构建失败!\n" && exit 1
else
  printf "✅ Maven 构建成功!\n"
fi

# TODO 5、查找生成的 JAR 文件是否存在
# find target -name "*.jar"：在 target 目录中查找所有 .jar 文件
# -not -name "*sources*"：排除文件名中包含 sources 的文件（通常是源码包）
# | head -1：只取第一个匹配的结果
JAR_FILE=$(find target -name "*.jar" -not -name "*sources*" | head -1)
# -z表示判断字符串是否为空【区别：-n表示判断字符串非空】
if [ -z "$JAR_FILE" ]; then
  echo "❌ 未找到 JAR 文件!" && exit 1
else
  echo "📁 找到 JAR 文件: $JAR_FILE"
fi

# TODO 6、构建 Docker 镜像
echo "🔨 构建 Docker 镜像..."
docker build -t ${app_name} "${project_dir}"
# $?表示上一条命令的退出状态码（0=成功；非0=失败），-ne：表示数值比较运算符，表示 "not equal"（不等于）
if [ $? -ne 0 ]; then  # 判断上一条命令的退出码是否不等于 0（即是否失败）
  printf "❌ Docker 镜像构建失败!\n" && exit 1
else
  printf "✅ Docker 镜像构建成功!\n"
fi

# TODO 7、启动应用镜像（后台运行容器）
echo "🚀 启动应用容器..."
docker run -p 8080:8080 --name ${app_name} \
  --link nacos-registry:nacos-registry \
  --link elasticsearch:es \
  --link logstash:logstash \
  --network docker-compose_mynet \
  -e TZ="Asia/Shanghai" \
  -v "${project_dir}/logs":/app/logs \
  -d ${app_name}
if [ $? -eq 0 ]; then
    echo "✅ 快速部署完成！容器 ${app_name} 已启动！"
    echo "🌐 访问地址: http://localhost:8080/user/10"
    echo "📋 查看日志: docker logs -f $app_name"
    echo "🛑 停止容器: docker stop $app_name"
else
    echo "❌ 容器启动失败!"
    exit 1
fi
